﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Microsoft.WindowsMobile.Samples.Location;
using GpSpotMe.Properties;

namespace GpSpotMe
{
    public partial class GpsSatellitePlotPanel : UserControl
    {
        private GpsPosition p;

        public GpsSatellitePlotPanel()
        {
            InitializeComponent();
        }

        public GpsPosition Datasource
        {
            get { return p; }
            set { p = value; }
        }

        public void DataBind()
        {
            dsSatellites.Satellites.Clear();
            //TODO: Hay un problema en el proxi del gpsmid que entrega un SatellitesInView no valido
            if (p != null && p.SatellitesInViewCountValid && p.SatellitesInViewCount > 0 && p.SatellitesInViewValid)
            {
                foreach (Satellite sat in p.SatellitesInView)
                {
                    bool inSol = (p.SatellitesInSolutionValid && Array.IndexOf(p.SatellitesInSolution, sat) > -1) ? true : false;
                    dsSatellites.Satellites.AddSatellitesRow(sat.Id, sat.Azimuth, sat.Elevation, sat.SignalStrength, inSol);
                }
            }
            this.Invalidate();
        }

        private void GpsSatellitePlotPanel_Paint(object sender, PaintEventArgs e)
        {
            //Paint the big circle
            Rectangle rect;

            if (this.ClientRectangle.Width > this.ClientRectangle.Height)
            {
                rect = new Rectangle(
                    ((this.ClientRectangle.Left + this.ClientRectangle.Right) / 2 - this.ClientRectangle.Height / 2),
                    this.ClientRectangle.Top,
                    this.ClientRectangle.Height,
                    this.ClientRectangle.Height);
            }
            else
            {
                rect = new Rectangle(
                    this.ClientRectangle.Left,
                    ((this.ClientRectangle.Top + this.ClientRectangle.Bottom) / 2 - this.ClientRectangle.Width / 2),
                    this.ClientRectangle.Width,
                    this.ClientRectangle.Width);
            }
            //e.Graphics.DrawImage(Resources.SatelliteMapBase, rect, new Rectangle(0,0,200,200), GraphicsUnit.Pixel);

            e.Graphics.DrawEllipse(new Pen(Color.Black), rect);

            //Small circles for satellites

            foreach (var sat in dsSatellites.Satellites)
            {
                const int radius = 10;
                float elevationPx = (90 - (float)sat.Elevation) / 90 * rect.Width / 2;
                float azimuthRad = (float)sat.Azimut * (float)Math.PI / 180;
                float xPx = elevationPx * (float)Math.Sin(azimuthRad);
                float yPx = elevationPx * (float)Math.Cos(azimuthRad);
                int x = rect.Left + rect.Width / 2 + (int)xPx;
                int y = rect.Top + rect.Height / 2 - (int)yPx;


                e.Graphics.FillEllipse(new SolidBrush(GetColorFromSnr(sat.Signal, sat.InSol)),
                                       x - radius, y - radius, 2 * radius, 2 * radius);

                e.Graphics.DrawString(sat.Id.ToString(), Font, new SolidBrush(Color.Black),
                    new Rectangle(x - radius, y - radius, 2 * radius, 2 * radius),
                    new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center, FormatFlags = StringFormatFlags.NoClip | StringFormatFlags.NoWrap });
            }
        }

        /// <summary>Gets color representation of satellite snr</summary>
        /// <param name="snr">Signal to noise ration</param>
        /// <param name="active">Is satellite used by lastGpsState?</param>
        /// <returns>Color representation of satellite state.</returns>
        private static Color GetColorFromSnr(int snr, bool active)
        {
            if (!active) return Color.Gray;
            if (snr == 0) return Color.Black;
            if (snr < 10) return Color.Red;
            if (snr <= 20) return Color.Yellow;
            return Color.Green;
        }
    }
}
